package com.zhan.rkforum.service;

import com.alibaba.fastjson.JSONObject;
import com.zhan.rkforum.bean.DiscussPost;
import com.zhan.rkforum.bean.Page;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ElasticSearchService{

    private static final Logger logger = LoggerFactory.getLogger(ElasticSearchService.class);

    @Value("${rkforum.elasticsearch.INDEX_NAME}")
    private String INDEX;

    @Autowired
    private RestHighLevelClient client;



    /**
     * 保存贴子到索引库
     *
     * @param post 帖子
     */
    public void saveDiscussPost(DiscussPost post) throws IOException {
        IndexRequest indexRequest = new IndexRequest(INDEX);
//        // 设置文档id
        indexRequest.id(String.valueOf(post.getId()));
        //设置请求超时时间为1s
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        // XContentType.JSON 表示声明请求数据的类型
        indexRequest.source(JSONObject.toJSONString(post), XContentType.JSON);
        IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
        //logger.info("创建文档的响应：{}", JSONObject.toJSONString(response));
    }

    /**
     * 删除索引库的贴子
     *
     * @param id id
     */
    public void deleteDiscussPost(int id) throws IOException {

        DeleteRequest request = new DeleteRequest(INDEX, String.valueOf(id));
        request.timeout(TimeValue.timeValueSeconds(1));
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
       // logger.info("响应结果：{}", JSONObject.toJSONString(response));

    }

    /**
     * 搜索
     *
     * @param keyword  关键字
     * @param page  分页参数
     * @return {@link List<DiscussPost>}
     * @throws Exception 异常
     */
    public List<DiscussPost> search(String keyword, Page page) throws Exception {


        //配置查询条件
        SearchRequest searchRequest = new SearchRequest(INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyword, "title", "content"))
                .sort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                .sort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                .timeout(TimeValue.timeValueMinutes(2))
                .from(page.getOffset())
                .size(page.getLimit());
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title")
                .field("content")
                .preTags("<em>")
                .postTags("</em>")
                .requireFieldMatch(false);
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        logger.info("查询状态：{}", JSONObject.toJSONString(response.status()));

        SearchHits hits = response.getHits();

        if (hits.getTotalHits().value <= 0) {
            page.setRows(0);
            logger.info("es搜索结果数量：{}", (int)hits.getTotalHits().value);
            return null;
        }else {
            page.setRows((int)hits.getTotalHits().value);
            logger.info("es搜索结果数量：{}", (int)hits.getTotalHits().value);
        }

        ArrayList<DiscussPost> list = new ArrayList<>();

        // 封装结果
        for (SearchHit hit : hits) {
            DiscussPost post = new DiscussPost();

            String id = hit.getSourceAsMap().get("id").toString();
            post.setId(Integer.parseInt(id));

            String userId = hit.getSourceAsMap().get("userId").toString();
            post.setUserId(String.valueOf(userId));

            String title = hit.getSourceAsMap().get("title").toString();
            post.setTitle(title);

            String content = hit.getSourceAsMap().get("content").toString();
            post.setContent(content);

            String status = hit.getSourceAsMap().get("status").toString();
            post.setStatus(Integer.parseInt(status));

            String createTime = hit.getSourceAsMap().get("createTime").toString();
            post.setCreateTime(new Date(Long.parseLong(createTime)));

            String commentCount = hit.getSourceAsMap().get("commentCount").toString();
            post.setCommentCount(Integer.parseInt(commentCount));

            // 处理高亮显示的结果
            HighlightField titleField = hit.getHighlightFields().get("title");
            if (titleField != null) {
                post.setTitle(titleField.getFragments()[0].toString());
            }

            HighlightField contentField = hit.getHighlightFields().get("content");
            if (contentField != null) {
                post.setContent(contentField.getFragments()[0].toString());
            }

            logger.info("discussPost: {}", JSONObject.toJSONString(post));

            list.add(post);
        }
        return list;
    }


}

